//////////////////////////////////////////////////////////////

//SOURCE FILE: logeo_disco.c

//PROCESO PLANIFICADOR DE DISCO

//Autor: Pablo Bergna

//////////////////////////////////////////////////////////////
#include "includes/todo_incluido.h"
#include "includes/tipos_disco.h"
#include "../includes/logeo_disco.h"


/***********************************************************************
FUNCION: VALIDAR_CHS

PROCESO: PPD

Autor: Pablo Bergna

PRE: chs_conf ya creado y alocado en memoria (es parte de td_disco)
	v_chs_target ya alocado en memoria y con datos ingresados (puede que no sean validos
	TODOS LOS VALORES DE CHS EMPIEZAN A PARTIR DE 1

POST:

DEVUELVE:	0 si chs valido
 			-1 si algun parametro de chs invalido (no dice cual)

FUNCION PPAL: valida que un chs dado pueda existir en el chs conf del disco
***********************************************************************/

int validar_chs(td_chs* chs_conf,td_chs v_chs_target){

	if (!((v_chs_target.cylinder > 0) &&
			(v_chs_target.cylinder <= chs_conf->cylinder))) return -1;

	if (!((v_chs_target.head > 0) &&
			(v_chs_target.head <= chs_conf->head))) return -1;

	if (!((v_chs_target.sector > 0) &&
			(v_chs_target.sector <= chs_conf->sector))) return -1;

	return 0;
}



/***********************************************************************
FUNCION: CALCULAR_TIEMPO_EN_ALCANZAR

PROCESO: PPD

Autor: Pablo Bergna

PRE: mi_disco ya creado y alocado en memoria
	v_chs_target ya alocado en memoria y con datos ingresados (puede que no sean validos
	tiempo ya creado

POST: al terminar queda el tiempo calculado en la variable tiempo

DEVUELVE:	0 si salio bien
 			-1 si salio mal (chs_target no valido)

FUNCION PPAL: calcula el tiempo en llegar desde el chs actual a un chs deseado
***********************************************************************/

int calcular_tiempo_en_alcanzar(td_disco* mi_disco,td_chs v_chs_target, int* tiempo){
	int aux=0,sectores_a_mover;

	if(validar_chs(mi_disco->chs_conf,v_chs_target) == -1){
		return -1;//CHS_TARGET INVALIDO
	}

	//calcula la diferencia entre pistas y la multiplica por el tiempo entre pistas
	*tiempo = (abs(mi_disco->current_chs->cylinder - v_chs_target.cylinder) * mi_disco->time_btw_track);

	//actualiza el sector del cabezal mientras se mueve de pista
	sectores_a_mover = (*tiempo/mi_disco->sector_spin); //calcula la division entera que es la cantidad de sectores que se mueve
	if ((*tiempo % mi_disco->sector_spin) != 0){
		sectores_a_mover ++;
	}

	//si el sector actual está por delante del sector deseado se debe llegar hasta el final de la pista para llegar a destino
	if (mi_disco->current_chs->sector > v_chs_target.sector){
		aux = (mi_disco->chs_conf->sector - mi_disco->current_chs->sector) + v_chs_target.sector;
	}
	else{
		aux = v_chs_target.sector - mi_disco->current_chs->sector;
	}
	//se multiplica la distancia de sectores por el tiempo que tarda en girar el disco por sector y se lo suma al tiempo previo entre pistas
	*tiempo = *tiempo + (aux * mi_disco->sector_spin);

	return 0;
}


/***********************************************************************
FUNCION: MOVER_CABEZAL

PROCESO: PPD

Autor: Pablo Bergna

PRE:

POST: disco contiene el puntero al archivo abierto

DEVUELVE: 0 si salio bien
		  -1 si hubo error en apertura

FUNCION PPAL: abre un archivo disco
***********************************************************************/

void mover_cabezal(td_disco* mi_disco,td_chs target){
	mi_disco->current_chs->cylinder = target.cylinder;
	mi_disco->current_chs->sector = target.sector;
	//<HACER>
	//falta que al ir pasando por cada lugar lo vaya logueando
}


/***********************************************************************
FUNCION: CONVERTIR_POSIC_EN_CHS

PROCESO: PPD

Autor: Pablo Bergna

PRE: chs_target ya alocada en memoria
	posicion viene con la direccion logica a convertir
	chs_conf ya alocada y llena con datos

POST: si sale bien se devuelve en chs_target la conversion

DEVUELVE: 0 si salio todo bien
		  -1 si salio mal

FUNCION PPAL: convierte una posicion de memoria logica a formato chs para buscarlo en el disco
***********************************************************************/

void convertir_posic_en_chs(int posicion,td_chs* chs_conf,td_chs* chs_target){
	uint16_t aux=0;

	chs_target->cylinder = (uint16_t)(posicion/chs_conf->cylinder);
	aux = posicion%chs_conf->cylinder; //en aux queda el resto de la division que es el sector
	chs_target->head = 1;
	chs_target->sector = (uint16_t)(aux);
}
